package base.day05;

import java.util.Stack;

/**
 * 描述：
 *      打印二叉树
 *      用递归的方式遍历二叉树，整个递归过程会经过每个节点三次，因此在这三次中的何时进行打印，区别了前中后序打印
 * @author hl
 * @version 1.0
 * @date 2020/10/27 14:42
 */
public class Code_01_PreInPosTraversal {
    public static void preOrderRecur(Node node){
        if (node == null) {
            return;
        }
        System.out.print(node.value + " ");
        preOrderRecur(node.left);
        preOrderRecur(node.right);
    }
    public static void inOrderRecur(Node node){
        if (node == null) {
            return;
        }
        inOrderRecur(node.left);
        System.out.print(node.value + " ");
        inOrderRecur(node.right);
    }
    public static void posOrderRecur(Node node){
        if (node == null) {
            return;
        }
        posOrderRecur(node.left);
        posOrderRecur(node.right);
        System.out.print(node.value + " ");
    }
    //**********************非递归版本*******************************

    public static void preOrderUnRecur(Node node){
        if (node != null) {
            Stack<Node> stack = new Stack<>();
            stack.push(node);
            while(!stack.isEmpty()){
                Node pop = stack.pop();
                System.out.print(pop.value + " ");
                if (pop.right != null) {
                    stack.push(pop.right);
                }
                if (pop.left != null) {
                    stack.push(pop.left);
                }
            }
        }
    }
    public static void inOrderUnRecur(Node head){
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            Node cur = head;
            while(!stack.isEmpty() || cur != null) {
                if(cur != null) {//只要当前节点不为空，将该子树的左边的节点全部压入
                    stack.push(cur);
                    cur = cur.left;
                }else {//左边为空了，从栈中取出父节点并打印
                    cur = stack.pop();
                    System.out.print(cur.value + " ");
                    cur = cur.right;
                }
            }
        }
    }
    public static void posOrderUnRecur(Node head){
        if (head != null) {
            Stack<Node> s1 = new Stack<>();//出s1栈的顺序中-右-左
            Stack<Node> s2 = new Stack<>();//按出s1栈的顺寻压入s2栈，s2栈的出栈顺序为左-右-中
            Node cur = head;
            s1.add(cur);
            while (!s1.isEmpty()){
                cur = s1.pop();
                s2.push(cur);
                if (cur.left != null) {
                    s1.push(cur.left);
                }
                if (cur.right != null) {
                    s1.push(cur.right);
                }
            }
            while(!s2.isEmpty()){//打印后序遍历
                System.out.print(s2.pop().value + " ");
            }
        }

    }

    public static void main(String[] args) {
        Node head = new Node(5);
        head.left = new Node(3);
        head.right = new Node(8);
        head.left.left = new Node(2);
        head.left.right = new Node(4);
        head.left.left.left = new Node(1);
        head.right.left = new Node(7);
        head.right.left.left = new Node(6);
        head.right.right = new Node(10);
        head.right.right.left = new Node(9);
        head.right.right.right = new Node(11);

        // recursive
        System.out.println("==============recursive==============");
        System.out.print("pre-order: ");
        preOrderRecur(head);
        System.out.println();
        System.out.print("in-order: ");
        inOrderRecur(head);
        System.out.println();
        System.out.print("pos-order: ");
        posOrderRecur(head);
        System.out.println();

        // unrecursive
        System.out.println();
        System.out.println("============unrecursive=============");
        preOrderUnRecur(head);
        System.out.println();
        inOrderUnRecur(head);
        System.out.println();
        posOrderUnRecur(head);
    }
}
